use core::ptr::NonNull;

/// FIO Pad控制器
pub struct FIOPadCtrl {
    pub base: NonNull<u8>,
}

// 为FIOPadCtrl实现Send和Sync特性，因为我们知道这个结构体可以在多线程间安全共享
unsafe impl Send for FIOPadCtrl {}
unsafe impl Sync for FIOPadCtrl {}

impl FIOPadCtrl {
    pub const fn new(base: *mut u8) -> Self {
        Self {
            base: NonNull::new(base).unwrap(),
        }
    }
}

/// FIO Pad功能枚举
#[repr(u32)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum FIOPadFunc {
    FUNC0 = 0,
    FUNC1 = 1,
    FUNC2 = 2,
    FUNC3 = 3,
    FUNC4 = 4,
    FUNC5 = 5,
    FUNC6 = 6,
}

/// 寄存器位操作宏
const fn genmask(high: usize, low: usize) -> u32 {
    ((1 << (high - low + 1)) - 1) << low
}

const fn get_reg32_bits(val: u32, high: usize, low: usize) -> u32 {
    (val & genmask(high, low)) >> low
}

const fn set_reg32_bits(val: u32, high: usize, low: usize) -> u32 {
    (val & genmask(high, low)) >> low
}

/// FIO Pad寄存器偏移量常量
pub const FIOPAD_REG0_PULL_MASK: u32 = genmask(9, 8);
pub const FIOPAD_REG0_DRIVE_MASK: u32 = genmask(7, 4);
pub const FIOPAD_REG0_FUNC_MASK: u32 = genmask(2, 0);

pub const fn fiopad_reg0_func_get(x: u32) -> u32 {
    get_reg32_bits(x, 2, 0)
}

pub const fn fiopad_reg0_func_set(x: u32) -> u32 {
    set_reg32_bits(x, 2, 0)
}

// 板级特定的寄存器偏移量
pub const FIOPAD_AN59_REG0_OFFSET: usize = 0x1D4;
pub const FIOPAD_N43_REG0_OFFSET: usize = 0x2AC;
pub const FIOPAD_AJ59_REG0_OFFSET: usize = 0x3B4;
pub const FIOPAD_AL59_REG0_OFFSET: usize = 0x3C4;
pub const FIOPAD_AJ57_REG0_OFFSET: usize = 0x3D4;
pub const FIOPAD_AG57_REG0_OFFSET: usize = 0x3EC;
pub const FIOPAD_AC59_REG0_OFFSET: usize = 0x404;
pub const FIOPAD_A41_REG0_OFFSET: usize = 0x444;
pub const FIOPAD_A43_REG0_OFFSET: usize = 0x454;
pub const FIOPAD_A45_REG0_OFFSET: usize = 0x464;
pub const FIOPAD_C45_REG0_OFFSET: usize = 0x474;
pub const FIOPAD_A47_REG0_OFFSET: usize = 0x484;
pub const FIOPAD_A49_REG0_OFFSET: usize = 0x494;
pub const FIOPAD_AR55_REG0_OFFSET: usize = 0x534;
pub const FIOPAD_W55_REG0_OFFSET: usize = 0x634;
pub const FIOPAD_W53_REG0_OFFSET: usize = 0x644;
pub const FIOPAD_U55_REG0_OFFSET: usize = 0x654;
pub const FIOPAD_U53_REG0_OFFSET: usize = 0x664;
pub const FIOPAD_AW51_REG0_OFFSET: usize = 0x684;
pub const FIOPAD_AU51_REG0_OFFSET: usize = 0x694;
pub const FIOPAD_AN49_REG0_OFFSET: usize = 0x6B4;
pub const FIOPAD_N45_REG0_OFFSET: usize = 0x6C4;
pub const FIOPAD_C49_REG0_OFFSET: usize = 0x704;
pub const FIOPAD_A51_REG0_OFFSET: usize = 0x714;
pub const FIOPAD_A37_REG0_OFFSET: usize = 0x784;
pub const FIOPAD_AC49_REG0_OFFSET: usize = 0x834;
pub const FIOPAD_AE47_REG0_OFFSET: usize = 0x844;
pub const FIOPAD_AA47_REG0_OFFSET: usize = 0x864;
pub const FIOPAD_AE59_REG0_OFFSET: usize = 0x8B4;
pub const FIOPAD_BA49_REG0_OFFSET: usize = 0x8F4;
pub const FIOPAD_AW55_REG0_OFFSET: usize = 0x914;